package com.ruoyi.quartz.task;

import com.google.common.util.concurrent.*;
import com.ruoyi.bizsys.domain.CreditAccount;
import com.ruoyi.bizsys.service.IApplyContactsService;
import com.ruoyi.bizsys.service.IDeviceContactsService;
import com.ruoyi.business.mapper.BCollectionMapper;
import com.ruoyi.business.service.impl.BLoanInfoServiceImpl;
import com.ruoyi.business.service.impl.CollectionDBServiceImpl;
import com.ruoyi.business.service.impl.CollectionServiceImpl;
import com.ruoyi.business.util.BathJobMonitorUtil;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.quartz.thread.CollectionTaskThread;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import com.ruoyi.business.service.ICollectionService;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Jamnsin
 * @Date: 2021/3/30 10:39 上午
 */
@Slf4j
@Component
public class CollectionTask {

    @Autowired
    ICollectionService collectionService;

    @Autowired
    BathJobMonitorUtil bathJobMonitorUtil;

    @Autowired
    private BCollectionMapper collectionMapper;

    @Autowired
    RedisCache redisCache;

    public static String theardName = "CollectionTask";

    @Autowired
    private CollectionDBServiceImpl collectionDBServiceImpl;

    @Autowired
    private ICollectionService iCollectionService;

    @Autowired
    private IApplyContactsService iApplyContactsService;

    @Autowired
    private IDeviceContactsService iDeviceContactsService;

    public void execute() {
        log.info("催收任务 Start >>>>>>>>>>");

        try {

            //创建剔除表数据
            iCollectionService.genExcludePhone();

            String repayDate = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_SLASH, DateUtils.addDays(new Date(), 3));

            //将今日入催客户数据进行备份
            collectionMapper.delZollectionContactsRelation();
            collectionMapper.addZollectionContactsRelation(repayDate);

            //同步今天的剔除数据到通讯录表
            iApplyContactsService.syncExcludePhone();
            iDeviceContactsService.syncExcludePhone();

           List<String> collectCustNos = collectionMapper.getOverdueCustNoAll(repayDate);
            int collectCustNosSize = collectCustNos.size();
            redisCache.setCacheObject(theardName+ BizConstants.MONITOR_COUNTNUMS, collectCustNosSize);
            log.info("催收跑批共有 {} 个客户需要执行", collectCustNosSize);

            collectionDBServiceImpl.delectCollectionInfo();

            String redisName = theardName+"-"+repayDate;

            int threadStep = 200;//每个线程执行的客户数
            //需要multiple个线程来执行
            int threadCount = collectCustNosSize / threadStep;
            if (threadCount * threadStep != collectCustNosSize) {
                threadCount++;
            }
            //线程计数器
            final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
            //线程池大小
            int poolSize = 5;

            ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
            ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);

            int threadAccountCount = 0;
            while (threadAccountCount != collectCustNosSize) {
                //分页取数startNum
                int startLimit = threadAccountCount;

                threadAccountCount += threadStep;

                if(threadAccountCount>collectCustNosSize){
                    threadAccountCount = collectCustNosSize;
                }

                String redisNameLimit = redisName+":"+startLimit+"-"+threadAccountCount;
                List<String> custNos = collectCustNos.subList(startLimit,threadAccountCount);
                redisCache.setCacheList(redisNameLimit,custNos);
                redisCache.expire(redisNameLimit,23, TimeUnit.HOURS);

                CollectionTaskThread thread = new CollectionTaskThread("["+theardName+"-"+startLimit+"]", redisNameLimit,
                        collectionService,redisCache);
                ListenableFuture listenableFuture = listeningExecutorService.submit(thread);

                Futures.addCallback(listenableFuture, new FutureCallback<String>() {
                    @Override
                    public void onSuccess(String result) {
                        countDownLatch.countDown();
                        log.info("["+this.getClass().getName()+"]线程处理结果："+ result);
                    }

                    @Override
                    public void onFailure(Throwable throwable) {
                        countDownLatch.countDown();
                        log.info("["+this.getClass().getName()+"]线程处理出错："+ throwable);
                    }
                });
            }
            countDownLatch.await(3*60, TimeUnit.MINUTES);//超过3个小时放弃

		} catch (Exception e) {
			log.error("催收任务执行异常", e);
            bathJobMonitorUtil.setRedis(CollectionServiceImpl.theardName,"",e.getMessage(),"催收任务执行异常");
		}

        log.info("催收任务 End >>>>>>>>>>");
    }

}
